import type { Request as IRequest } from 'express';
export const UA_VERSIONS = {
    Edge: /(?:edge|edga|edgios|edg)\/([\d\w\.\-]+)/i,
    Firefox: /(?:firefox|fxios)\/([\d\w\.\-]+)/i,
    IE: /msie\s([\d\.]+[\d])|trident\/\d+\.\d+;.*[rv:]+(\d+\.\d)/i,
    Chrome: /(?:chrome|crios)\/([\d\w\.\-]+)/i,
    Chromium: /chromium\/([\d\w\.\-]+)/i,
    Safari: /(version|safari)\/([\d\w\.\-]+)/i,
    Opera: /version\/([\d\w\.\-]+)|OPR\/([\d\w\.\-]+)/i,
    Ps3: /([\d\w\.\-]+)\)\s*$/i,
    Psp: /([\d\w\.\-]+)\)?\s*$/i,
    Amaya: /amaya\/([\d\w\.\-]+)/i,
    SeaMonkey: /seamonkey\/([\d\w\.\-]+)/i,
    OmniWeb: /omniweb\/v([\d\w\.\-]+)/i,
    Flock: /flock\/([\d\w\.\-]+)/i,
    Epiphany: /epiphany\/([\d\w\.\-]+)/i,
    WinJs: /msapphost\/([\d\w\.\-]+)/i,
    PhantomJS: /phantomjs\/([\d\w\.\-]+)/i,
    AlamoFire: /alamofire\/([\d\w\.\-]+)/i,
    UC: /ucbrowser\/([\d\w\.]+)/i,
    Facebook: /FBAV\/([\d\w\.]+)/i,
    WebKit: /applewebkit\/([\d\w\.]+)/i,
    Wechat: /micromessenger\/([\d\w\.]+)/i,
    Electron: /Electron\/([\d\w\.]+)/i
};
export const UA_BROWSERS = {
    YaBrowser: /yabrowser/i,
    Edge: /edge|edga|edgios|edg/i,
    Amaya: /amaya/i,
    Konqueror: /konqueror/i,
    Epiphany: /epiphany/i,
    SeaMonkey: /seamonkey/i,
    Flock: /flock/i,
    OmniWeb: /omniweb/i,
    Chromium: /chromium/i,
    Chrome: /chrome|crios/i,
    Safari: /safari/i,
    IE: /msie|trident/i,
    Opera: /opera|OPR\//i,
    PS3: /playstation 3/i,
    PSP: /playstation portable/i,
    Firefox: /firefox|fxios/i,
    WinJs: /msapphost/i,
    PhantomJS: /phantomjs/i,
    AlamoFire: /alamofire/i,
    UC: /UCBrowser/i,
    Facebook: /FBA[NV]/
};
export const UA_PLATFORM = {
    Windows: /windows nt/i,
    WindowsPhone: /windows phone/i,
    Mac: /macintosh/i,
    Linux: /linux/i,
    Wii: /wii/i,
    Playstation: /playstation/i,
    iPad: /ipad/i,
    iPod: /ipod/i,
    iPhone: /iphone/i,
    Android: /android/i,
    Blackberry: /blackberry/i,
    Samsung: /samsung/i,
    Curl: /curl/i,
    Electron: /Electron/i,
    iOS: /^ios\-/i
};
const BOTS = [
    '\\+https:\\/\\/developers.google.com\\/\\+\\/web\\/snippet\\/',
    'ad\\smonitoring',
    'adsbot',
    'apex',
    'applebot',
    'archive.org_bot',
    'baiduspider',
    'bingbot',
    'chromeheadless',
    'cloudflare',
    'cloudinary',
    'crawler',
    'curl',
    'discordbot',
    'duckduckbot',
    'embedly',
    'exabot',
    'facebookexternalhit',
    'facebot',
    'flipboard',
    'google',
    'googlebot',
    'gsa-crawler',
    'gurujibot',
    'guzzlehttp',
    'heritrix',
    'ia_archiver',
    'insights',
    'linkedinbot',
    'ltx71',
    'mediapartners',
    'msnbot',
    'odklbot',
    'phantom\\.js',
    'phantomjs',
    'pingdom',
    'pinterest',
    'python',
    'rtlnieuws',
    'skypeuripreview',
    'slackbot',
    'slurp',
    'spbot',
    'telegrambot',
    'test\\scertificate',
    'testing',
    'tiabot',
    'tumblr ',
    'twitterbot',
    'vkshare',
    'web\\sscraper',
    'wget',
    'yandexbot',
    'whatsapp',
    'orangebot',
    'smtbot',
    'qwantify',
    'mj12bot',
    'ahrefsbot',
    'seznambot',
    'panscient\.com',
    'duckduckgo-favicons-bot',
    'uptimerobot',
    'semrushbot',
    'postman',
    'dotbot',
    'zoominfobot',
    'ifttt',
    'sogou',
    'ru_bot',
    'researchscan',
    'nimbostratus-bot',
    'slack-imgproxy',
    'node-superagent',
    'go-http-client',
    'jersey',
    'dataprovider.com',
    'github-camo',
    'dispatch',
    'checkmarknetwork',
    'screaming frog',
    'whatweb',
    'daum',
    'netcraftsurveyagent',
    'mojeekbot',
    'surdotlybot',
    'springbot'
];
const IS_BOT_REGEXP = new RegExp('^.*(' + BOTS.join('|') + ').*$');
export const UA_OS = {
    Windows10: /windows nt 10\.0/i,
    Windows81: /windows nt 6\.3/i,
    Windows8: /windows nt 6\.2/i,
    Windows7: /windows nt 6\.1/i,
    UnknownWindows: /windows nt 6\.\d+/i,
    WindowsVista: /windows nt 6\.0/i,
    Windows2003: /windows nt 5\.2/i,
    WindowsXP: /windows nt 5\.1/i,
    Windows2000: /windows nt 5\.0/i,
    WindowsPhone81: /windows phone 8\.1/i,
    WindowsPhone80: /windows phone 8\.0/i,
    OSXCheetah: /os x 10[._]0/i,
    OSXPuma: /os x 10[._]1(\D|$)/i,
    OSXJaguar: /os x 10[._]2/i,
    OSXPanther: /os x 10[._]3/i,
    OSXTiger: /os x 10[._]4/i,
    OSXLeopard: /os x 10[._]5/i,
    OSXSnowLeopard: /os x 10[._]6/i,
    OSXLion: /os x 10[._]7/i,
    OSXMountainLion: /os x 10[._]8/i,
    OSXMavericks: /os x 10[._]9/i,
    OSXYosemite: /os x 10[._]10/i,
    OSXElCapitan: /os x 10[._]11/i,
    MacOSSierra: /os x 10[._]12/i,
    MacOSHighSierra: /os x 10[._]13/i,
    MacOSMojave: /os x 10[._]14/i,
    Mac: /os x/i,
    Linux: /linux/i,
    Linux64: /linux x86\_64/i,
    ChromeOS: /cros/i,
    Wii: /wii/i,
    PS3: /playstation 3/i,
    PSP: /playstation portable/i,
    iPad: /\(iPad.*os (\d+)[._](\d+)/i,
    iPhone: /\(iPhone.*os (\d+)[._](\d+)/i,
    iOS: /ios/i,
    Bada: /Bada\/(\d+)\.(\d+)/i,
    Curl: /curl\/(\d+)\.(\d+)\.(\d+)/i,
    Electron: /Electron\/(\d+)\.(\d+)\.(\d+)/i,
}
export class UserAgent {
    isWindows: boolean = false;
    isWindowsPhone: boolean = false;
    isLinux: boolean = false;
    isLinux64: boolean = false;
    isChromeOS: boolean = false;
    isMac: boolean = false;
    isiPad: boolean = false;
    isiPhone: boolean = false;
    isBada: boolean = false;
    isCurl: boolean = false;
    isElectron: boolean = false;
    isAndroid: boolean = false;
    isBlackberry: boolean = false;
    isiPod: boolean = false;
    isSamsung: boolean = false;
    isAuthoritative: boolean = false;
    isUC: boolean = false;
    isSafari: boolean = false;
    isFirefox: boolean = false;
    isIE: boolean = false;
    isWinJs: boolean = false;
    isChrome: boolean = false;
    isFacebook: boolean = false;
    isOpera: boolean = false;
    isOmniWeb: boolean = false;
    isFlock: boolean = false;
    isSeaMonkey: boolean = false;
    isEpiphany: boolean = false;
    isAmaya: boolean = false;
    isKonqueror: boolean = false;
    isPhantomJS: boolean = false;
    isEdge: boolean = false;
    isYaBrowser: boolean = false;
    isAlamoFire: boolean = false;
    /**
     * os
     */
    os?: string;
    platform?: string;
    browser?: string;
    source?: string;
    browserVersion?: string;
    electronVersion?: string;
    kindleFire: string | false = false;
    constructor(req: IRequest) {
        const { headers } = req;
        const ua = headers['user-agent'];
        this.parse(ua);
    }
    parse(source?: string) {
        if (!source) return;
        source = source.replace(/^\s*/, '').replace(/\s*$/, '')
        this.source = source;
        this.os = this.getOS(source);
        this.platform = this.getPlatform(source);
        this.browser = this.getBrowser(source);
        this.testWechat();
        this.browserVersion = this.getBrowserVersion(source)
        this.version = parseInt(this.browserVersion!, 10)
        this.electronVersion = this.getElectronVersion(source)
        this.kindleFire = this.testKindleFire();
        this.testWebkit();
        this.testCaptiveNetwork();
        this.testBot();
        this.testSmartTV();
        this.testMobile();
        this.testAndroidTablet();
        this.testTablet();
        this.testCompatibilityMode();
        this.testSilk();
    }
    isWechat: boolean = false;
    private testWechat() {
        if (/micromessenger/i.test(this.source!)) {
            this.isWechat = true;
            this.browserVersion = this.getWechatVersion(this.source!);
        }
    }
    getWechatVersion(string: string) {
        if (UA_VERSIONS.Wechat.test(string)) {
            return RegExp.$1;
        }
        return 'unknown';
    };
    private getOS(source: string) {
        switch (true) {
            case UA_OS.WindowsVista.test(source):
                this.isWindows = true;
                return 'Windows Vista';
            case UA_OS.Windows7.test(source):
                this.isWindows = true;
                return 'Windows 7';
            case UA_OS.Windows8.test(source):
                this.isWindows = true;
                return 'Windows 8';
            case UA_OS.Windows81.test(source):
                this.isWindows = true;
                return 'Windows 8.1';
            case UA_OS.Windows10.test(source):
                this.isWindows = true;
                return 'Windows 10.0';
            case UA_OS.Windows2003.test(source):
                this.isWindows = true;
                return 'Windows 2003';
            case UA_OS.WindowsXP.test(source):
                this.isWindows = true;
                return 'Windows XP';
            case UA_OS.Windows2000.test(source):
                this.isWindows = true;
                return 'Windows 2000';
            case UA_OS.WindowsPhone81.test(source):
                this.isWindowsPhone = true;
                return 'Windows Phone 8.1';
            case UA_OS.WindowsPhone80.test(source):
                this.isWindowsPhone = true;
                return 'Windows Phone 8.0';
            case UA_OS.Linux64.test(source):
                this.isLinux = true;
                this.isLinux64 = true;
                return 'Linux 64';
            case UA_OS.Linux.test(source):
                this.isLinux = true;
                return 'Linux';
            case UA_OS.ChromeOS.test(source):
                this.isChromeOS = true;
                return 'Chrome OS';
            case UA_OS.Wii.test(source):
                return 'Wii';
            case UA_OS.PS3.test(source):
                return 'Playstation';
            case UA_OS.PSP.test(source):
                return 'Playstation';
            case UA_OS.OSXCheetah.test(source):
                this.isMac = true;
                return 'OS X Cheetah';
            case UA_OS.OSXPuma.test(source):
                this.isMac = true;
                return 'OS X Puma';
            case UA_OS.OSXJaguar.test(source):
                this.isMac = true;
                return 'OS X Jaguar';
            case UA_OS.OSXPanther.test(source):
                this.isMac = true;
                return 'OS X Panther';
            case UA_OS.OSXTiger.test(source):
                this.isMac = true;
                return 'OS X Tiger';
            case UA_OS.OSXLeopard.test(source):
                this.isMac = true;
                return 'OS X Leopard';
            case UA_OS.OSXSnowLeopard.test(source):
                this.isMac = true;
                return 'OS X Snow Leopard';
            case UA_OS.OSXLion.test(source):
                this.isMac = true;
                return 'OS X Lion';
            case UA_OS.OSXMountainLion.test(source):
                this.isMac = true;
                return 'OS X Mountain Lion';
            case UA_OS.OSXMavericks.test(source):
                this.isMac = true;
                return 'OS X Mavericks';
            case UA_OS.OSXYosemite.test(source):
                this.isMac = true;
                return 'OS X Yosemite';
            case UA_OS.OSXElCapitan.test(source):
                this.isMac = true;
                return 'OS X El Capitan';
            case UA_OS.MacOSSierra.test(source):
                this.isMac = true;
                return 'macOS Sierra';
            case UA_OS.MacOSHighSierra.test(source):
                this.isMac = true;
                return 'macOS High Sierra';
            case UA_OS.MacOSMojave.test(source):
                this.isMac = true;
                return 'macOS Mojave';
            case UA_OS.Mac.test(source):
                // !('ontouchend' in document);
                // navigator.maxTouchPoints > 1
                this.isMac = true;
                return 'OS X';
            case UA_OS.iPad.test(source):
                // 'ontouchend' in document;
                this.isiPad = true;
                return source.match(UA_OS.iPad)![0].replace('_', '.');
            case UA_OS.iPhone.test(source):
                //  'ontouchend' in document;
                this.isiPhone = true;
                return source.match(UA_OS.iPhone)![0].replace('_', '.');
            case UA_OS.Bada.test(source):
                this.isBada = true;
                return 'Bada';
            case UA_OS.Curl.test(source):
                this.isCurl = true;
                return 'Curl';
            case UA_OS.iOS.test(source):
                this.isiPhone = true;
                return 'iOS';
            case UA_OS.Electron.test(source):
                this.isElectron = true;
                return 'Electron';
            default:
                return 'unknown';
        }
    }
    private getPlatform(string: string) {
        switch (true) {
            case UA_PLATFORM.Windows.test(string):
                return 'Microsoft Windows';
            case UA_PLATFORM.WindowsPhone.test(string):
                this.isWindowsPhone = true;
                return 'Microsoft Windows Phone';
            case UA_PLATFORM.Mac.test(string):
                return 'Apple Mac';
            case UA_PLATFORM.Curl.test(string):
                return 'Curl';
            case UA_PLATFORM.Electron.test(string):
                this.isElectron = true;
                return 'Electron';
            case UA_PLATFORM.Android.test(string):
                this.isAndroid = true;
                return 'Android';
            case UA_PLATFORM.Blackberry.test(string):
                this.isBlackberry = true;
                return 'Blackberry';
            case UA_PLATFORM.Linux.test(string):
                return 'Linux';
            case UA_PLATFORM.Wii.test(string):
                return 'Wii';
            case UA_PLATFORM.Playstation.test(string):
                return 'Playstation';
            case UA_PLATFORM.iPad.test(string):
                this.isiPad = true;
                return 'iPad';
            case UA_PLATFORM.iPod.test(string):
                this.isiPod = true;
                return 'iPod';
            case UA_PLATFORM.iPhone.test(string):
                this.isiPhone = true;
                return 'iPhone';
            case UA_PLATFORM.Samsung.test(string):
                this.isSamsung = true;
                return 'Samsung';
            case UA_PLATFORM.iOS.test(string):
                return 'Apple iOS';
            default:
                return 'unknown';
        }
    }
    private getBrowser(string: string) {
        switch (true) {
            case UA_BROWSERS.YaBrowser.test(string):
                this.isYaBrowser = true;
                return 'YaBrowser';
            case UA_BROWSERS.AlamoFire.test(string):
                this.isAlamoFire = true;
                return 'AlamoFire';
            case UA_BROWSERS.Edge.test(string):
                this.isEdge = true;
                return 'Edge';
            case UA_BROWSERS.PhantomJS.test(string):
                this.isPhantomJS = true;
                return 'PhantomJS';
            case UA_BROWSERS.Konqueror.test(string):
                this.isKonqueror = true;
                return 'Konqueror';
            case UA_BROWSERS.Amaya.test(string):
                this.isAmaya = true;
                return 'Amaya';
            case UA_BROWSERS.Epiphany.test(string):
                this.isEpiphany = true;
                return 'Epiphany';
            case UA_BROWSERS.SeaMonkey.test(string):
                this.isSeaMonkey = true;
                return 'SeaMonkey';
            case UA_BROWSERS.Flock.test(string):
                this.isFlock = true;
                return 'Flock';
            case UA_BROWSERS.OmniWeb.test(string):
                this.isOmniWeb = true;
                return 'OmniWeb';
            case UA_BROWSERS.Opera.test(string):
                this.isOpera = true;
                return 'Opera';
            case UA_BROWSERS.Chromium.test(string):
                this.isChrome = true;
                return 'Chromium';
            case UA_BROWSERS.Facebook.test(string):
                this.isFacebook = true;
                return 'Facebook';
            case UA_BROWSERS.Chrome.test(string):
                this.isChrome = true;
                return 'Chrome';
            case UA_BROWSERS.WinJs.test(string):
                this.isWinJs = true;
                return 'WinJs';
            case UA_BROWSERS.IE.test(string):
                this.isIE = true;
                return 'IE';
            case UA_BROWSERS.Firefox.test(string):
                this.isFirefox = true;
                return 'Firefox';
            case UA_BROWSERS.Safari.test(string):
                this.isSafari = true;
                return 'Safari';
            case UA_BROWSERS.PS3.test(string):
                return 'ps3';
            case UA_BROWSERS.PSP.test(string):
                return 'psp';
            case UA_BROWSERS.UC.test(string):
                this.isUC = true;
                return 'UCBrowser';
            default:
                if (string.indexOf('Dalvik') !== -1) {
                    return 'unknown';
                }
                // If the UA does not start with Mozilla guess the user agent.
                if (string.indexOf('Mozilla') !== 0 && /^([\d\w\-\.]+)\/[\d\w\.\-]+/i.test(string)) {
                    this.isAuthoritative = false;
                    return RegExp.$1;
                }
                return 'unknown';
        }
    }
    private getBrowserVersion(string: string) {
        switch (this.browser) {
            case 'Edge':
                if (UA_VERSIONS.Edge.test(string)) {
                    return RegExp.$1;
                }
                break;
            case 'PhantomJS':
                if (UA_VERSIONS.PhantomJS.test(string)) {
                    return RegExp.$1;
                }
                break;
            case 'Chrome':
                if (UA_VERSIONS.Chrome.test(string)) {
                    return RegExp.$1;
                }
                break;
            case 'Chromium':
                if (UA_VERSIONS.Chromium.test(string)) {
                    return RegExp.$1;
                }
                break;
            case 'Safari':
                if (UA_VERSIONS.Safari.test(string)) {
                    return RegExp.$2;
                }
                break;
            case 'Opera':
                if (UA_VERSIONS.Opera.test(string)) {
                    return RegExp.$1 ? RegExp.$1 : RegExp.$2;
                }
                break;
            case 'Firefox':
                if (UA_VERSIONS.Firefox.test(string)) {
                    return RegExp.$1;
                }
                break;
            case 'WinJs':
                if (UA_VERSIONS.WinJs.test(string)) {
                    return RegExp.$1;
                }
                break;
            case 'IE':
                if (UA_VERSIONS.IE.test(string)) {
                    return RegExp.$2 ? RegExp.$2 : RegExp.$1;
                }
                break;
            case 'ps3':
                if (UA_VERSIONS.Ps3.test(string)) {
                    return RegExp.$1;
                }
                break;
            case 'psp':
                if (UA_VERSIONS.Psp.test(string)) {
                    return RegExp.$1;
                }
                break;
            case 'Amaya':
                if (UA_VERSIONS.Amaya.test(string)) {
                    return RegExp.$1;
                }
                break;
            case 'Epiphany':
                if (UA_VERSIONS.Epiphany.test(string)) {
                    return RegExp.$1;
                }
                break;
            case 'SeaMonkey':
                if (UA_VERSIONS.SeaMonkey.test(string)) {
                    return RegExp.$1;
                }
                break;
            case 'Flock':
                if (UA_VERSIONS.Flock.test(string)) {
                    return RegExp.$1;
                }
                break;
            case 'OmniWeb':
                if (UA_VERSIONS.OmniWeb.test(string)) {
                    return RegExp.$1;
                }
                break;
            case 'UCBrowser':
                if (UA_VERSIONS.UC.test(string)) {
                    return RegExp.$1;
                }
                break;
            case 'Facebook':
                if (UA_VERSIONS.Facebook.test(string)) {
                    return RegExp.$1;
                }
                break;
            default:
                if (this.browser !== 'unknown') {
                    const regex = new RegExp(this.browser + '[\\/ ]([\\d\\w\\.\\-]+)', 'i');
                    if (regex.test(string)) {
                        return RegExp.$1;
                    }
                } else {
                    this.testWebkit();
                    if (this.isWebkit && UA_VERSIONS.WebKit.test(string)) {
                        return RegExp.$1;
                    }
                    return 'unknown';
                }
        }
    }
    isWebkit: boolean = false;
    private testWebkit() {
        if (this.browser === 'unknown' && /applewebkit/i.test(this.source!)) {
            this.browser = 'Apple WebKit';
            this.isWebkit = true;
        }
    }
    private getElectronVersion(string: string) {
        if (UA_VERSIONS.Electron.test(string)) {
            this.isElectron = true;
            return RegExp.$1;
        }
        return '';
    }
    isBot: boolean | string = false;
    private testBot() {
        const isBot = IS_BOT_REGEXP.exec(this.source!.toLowerCase());
        if (isBot) {
            this.isBot = isBot[1];
        } else if (!this.isAuthoritative) {
            // Test unauthoritative parse for `bot` in UA to flag for bot
            this.isBot = /bot/i.test(this.source!);
        }
    }
    isSmartTV: boolean = false;
    private testSmartTV() {
        this.isSmartTV = new RegExp('smart-tv|smarttv|googletv|appletv|hbbtv|pov_tv|netcast.tv', 'gi').test(this.source!.toLowerCase());
    }
    private testMobile() {
        switch (true) {
            case this.isWindows:
            case this.isLinux:
            case this.isMac:
            case this.isChromeOS:
                this.isDesktop = true;
                break;
            case this.isAndroid:
            case this.isSamsung:
                this.isMobile = true;
                break;
            default:
        }
        switch (true) {
            case this.isiPad:
            case this.isiPod:
            case this.isiPhone:
            case this.isBada:
            case this.isBlackberry:
            case this.isAndroid:
            case this.isWindowsPhone:
                this.isMobile = true;
                this.isDesktop = false;
                break;
            default:
        }
        if (/mobile|^ios\-/i.test(this.source!)) {
            this.isMobile = true;
            this.isDesktop = false;
        }
        if (/dalvik/i.test(this.source!)) {
            this.isAndroidNative = true;
            this.isMobileNative = true;
        }
        if (/scale/i.test(this.source!)) {
            this.isiPhoneNative = true;
            this.isMobileNative = true;
        }
    }
    isMobile: boolean = false;
    isDesktop: boolean = false;
    isAndroidNative: boolean = false;
    isiPhoneNative: boolean = false;
    isMobileNative: boolean = false;

    private testAndroidTablet() {
        if (this.isAndroid && !/mobile/i.test(this.source!)) {
            this.isAndroidTablet = true;
        }
    }

    isAndroidTablet: boolean = false;
    isKindleFire: boolean = false;
    isTablet: boolean = false;
    private testTablet() {
        switch (true) {
            case this.isiPad:
            case this.isAndroidTablet:
            case this.isKindleFire:
                this.isTablet = true;
                break;
        }
        if (/tablet/i.test(this.source!)) {
            this.isTablet = true;
        }
    }
    private testKindleFire() {
        switch (true) {
            case /KFOT/gi.test(this.source!):
                this.isKindleFire = true;
                return 'Kindle Fire';
            case /KFTT/gi.test(this.source!):
                this.isKindleFire = true;
                return 'Kindle Fire HD';
            case /KFJWI/gi.test(this.source!):
                this.isKindleFire = true;
                return 'Kindle Fire HD 8.9';
            case /KFJWA/gi.test(this.source!):
                this.isKindleFire = true;
                return 'Kindle Fire HD 8.9 4G';
            case /KFSOWI/gi.test(this.source!):
                this.isKindleFire = true;
                return 'Kindle Fire HD 7';
            case /KFTHWI/gi.test(this.source!):
                this.isKindleFire = true;
                return 'Kindle Fire HDX 7';
            case /KFTHWA/gi.test(this.source!):
                this.isKindleFire = true;
                return 'Kindle Fire HDX 7 4G';
            case /KFAPWI/gi.test(this.source!):
                this.isKindleFire = true;
                return 'Kindle Fire HDX 8.9';
            case /KFAPWA/gi.test(this.source!):
                this.isKindleFire = true;
                return 'Kindle Fire HDX 8.9 4G';
            default:
                return false;
        }
    }

    version?: number;
    isIECompatibilityMode: boolean = false;

    private testCompatibilityMode() {
        if (this.isIE) {
            if (/Trident\/(\d)\.0/i.test(this.source!)) {
                const tridentVersion = parseInt(RegExp.$1, 10);
                const version = parseInt(`${this.version}`, 10);
                if (version === 7 && tridentVersion === 7) {
                    this.isIECompatibilityMode = true;
                    this.version = 11.0;
                }
                if (version === 7 && tridentVersion === 6) {
                    this.isIECompatibilityMode = true;
                    this.version = 10.0;
                }
                if (version === 7 && tridentVersion === 5) {
                    this.isIECompatibilityMode = true;
                    this.version = 9.0;
                }
                if (version === 7 && tridentVersion === 4) {
                    this.isIECompatibilityMode = true;
                    this.version = 8.0;
                }
            }
        }
    }

    isSilk: boolean = false;
    SilkAccelerated: boolean = false;
    private testSilk() {
        switch (true) {
            case new RegExp('silk', 'gi').test(this.source!):
                this.isSilk = true;
                break;
            default:
        }

        if (/Silk-Accelerated=true/gi.test(this.source!)) {
            this.SilkAccelerated = true;
        }
        return this.isSilk ? 'Silk' : false;
    }
    isCaptive: boolean = false;
    private testCaptiveNetwork() {
        switch (true) {
            case /CaptiveNetwork/gi.test(this.source!):
                this.isCaptive = true;
                this.isMac = true;
                this.platform = 'Apple Mac';
                return 'CaptiveNetwork';
            default:
                return false;
        }
    }
    toJson() {
        return {
            isWechat: this.isWechat,
            isCaptive: this.isCaptive,
            isSilk: this.isSilk,
            SilkAccelerated: this.SilkAccelerated,
            version: this.version,
            isIECompatibilityMode: this.isIECompatibilityMode,
            isAndroidTablet: this.isAndroidTablet,
            isKindleFire: this.isKindleFire,
            isTablet: this.isTablet,
            kindleFire: this.kindleFire,
            isMobile: this.isMobile,
            isDesktop: this.isDesktop,
            isAndroidNative: this.isAndroidNative,
            isiPhoneNative: this.isiPhoneNative,
            isMobileNative: this.isMobileNative,
            isSmartTV: this.isSmartTV,
            isBot: this.isBot,
            isWebkit: this.isWebkit,
            isWindows: this.isWindows,
            isWindowsPhone: this.isWindowsPhone,
            isLinux: this.isLinux,
            isLinux64: this.isLinux64,
            isChromeOS: this.isChromeOS,
            isMac: this.isMac,
            isiPad: this.isiPad,
            isiPhone: this.isiPhone,
            isBada: this.isBada,
            isCurl: this.isCurl,
            isElectron: this.isElectron,
            isAndroid: this.isAndroid,
            isBlackberry: this.isBlackberry,
            isiPod: this.isiPod,
            isSamsung: this.isSamsung,
            isAuthoritative: this.isAuthoritative,
            isUC: this.isUC,
            isSafari: this.isSafari,
            isFirefox: this.isFirefox,
            isIE: this.isIE,
            isWinJs: this.isWinJs,
            isChrome: this.isChrome,
            isFacebook: this.isFacebook,
            isOpera: this.isOpera,
            isOmniWeb: this.isOmniWeb,
            isFlock: this.isFlock,
            isSeaMonkey: this.isSeaMonkey,
            isEpiphany: this.isEpiphany,
            isAmaya: this.isAmaya,
            isKonqueror: this.isKonqueror,
            isPhantomJS: this.isPhantomJS,
            isEdge: this.isEdge,
            isYaBrowser: this.isYaBrowser,
            isAlamoFire: this.isAlamoFire,
            os: this.os,
            platform: this.platform,
            browser: this.browser,
            browserVersion: this.browserVersion,
            electronVersion: this.electronVersion,
        };
    }

    toString() {
        return JSON.stringify(this.toJson(), null, 2)
    }
}